﻿#include "LoginWidget.h"
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QRegularExpressionValidator>
#include <QShortcut>
#include <QTimer>
#include <QValidator>
#include "Custom/CircleButton.h"
#include "Debug.h"
#include "MainWidget.h"
#include "Model/DataCenter.h"
#include "Toast.h"
#include "VerifyCodeWidget.h"

using namespace model;

LoginWidget*      LoginWidget::instance       = nullptr;
PhoneLoginWidget* LoginWidget::phone_instance = nullptr;

//////////////////////////////////////////
/// @brief 使用QQ号的登录界面
//////////////////////////////////////////
LoginWidget::LoginWidget(QWidget* parent)
{
    /* 设置QWidget基本属性 */
    this->setStyleSheet(
        "QWidget{"
        "background-color: #FFFFFF;"
        "}");
    this->setParent(parent);
    this->setFixedSize(QSize(320, 380));
    this->setWindowTitle("QQ登录");
    this->setWindowIcon(QIcon(":/image/logo.png"));
    this->setAttribute(Qt::WA_DeleteOnClose);
    data_center = DataCenter::get_instance();
    init_main_ui();
    connect_signals();
}

LoginWidget::~LoginWidget()
{
    instance = nullptr;  // 重置静态指针
}

/// @brief 获取登录窗口实例
LoginWidget* LoginWidget::get_instance()
{
    if (!instance) {
        instance = new LoginWidget();
    }
    return instance;
}

/// @brief 获取手机登录窗口实例
PhoneLoginWidget* LoginWidget::get_phone_instance()
{
    if (!phone_instance) {
        phone_instance = new PhoneLoginWidget();
    }
    return phone_instance;
}

/// @brief 切换登录/注册模式
void LoginWidget::toggle_mode()
{
    login_mode = !login_mode;  // 切换模式

    if (login_mode) {
        this->setWindowTitle("QQ登录");
        user_edit->setPlaceholderText("输入QQ号");
        password_edit->setPlaceholderText("输入QQ密码");
        register_btn->setText("QQ注册");
        login_button->setText("登录");
    } else {
        this->setWindowTitle("QQ注册");
        user_edit->setPlaceholderText("输入QQ号");
        password_edit->setPlaceholderText("输入密码");
        register_btn->setText("QQ登录");
        login_button->setText("注册");
    }
}

/// @brief 初始化主要的UI
void LoginWidget::init_main_ui()
{
    g_layout = new QGridLayout();
    // g_layout->setSpacing(10);
    g_layout->setHorizontalSpacing(20);
    g_layout->setVerticalSpacing(15);
    g_layout->setContentsMargins(20, 30, 20, 20);
    this->setLayout(g_layout);
    /* 常量定义 */
    const static int AVATA_HEIGHT      = 75;                 // 头像高度
    const static int AVATA_WIDTH       = 75;                 // 头像宽度
    const static int EDIT_HEIGHT       = 40;                 // 输入框高度
    const static int CODE_EDIT_WIDTH   = this->width() / 2;  // 验证码输入框宽度, 留出一部分给验证码图片
    const static int BTN_HEIGHT        = 35;                 // 按钮高度
    const static int BOTOM_LABEL_WIDTH = 60;                 // 底部两个QLabel的宽度
    /* 头像 */
    CircleButton* avatar = new CircleButton();
    avatar->setIcon(QIcon(":/image/defaultAvatar.png"));
    avatar->setFixedSize(QSize(AVATA_WIDTH, AVATA_HEIGHT));
    avatar->setIconSize(QSize(AVATA_WIDTH, AVATA_HEIGHT));
    /* 两个输入框 */
    LINE_EDIT_STYLE +=
        "QLineEdit {"
        "font-size: 14px;"
        "}";
    user_edit = new QLineEdit();
    user_edit->setAlignment(Qt::AlignHCenter);  // 字体水平居中
    user_edit->setPlaceholderText("输入QQ号");
    user_edit->setStyleSheet(LINE_EDIT_STYLE);  // 设置输入框样式
    user_edit->setFixedHeight(EDIT_HEIGHT);     // 设置输入框高度
    QRegularExpression reg("^[1-9]{1}[0-9]{4,14}$");
    user_edit->setValidator(new QRegularExpressionValidator(reg));
    password_edit = new QLineEdit();
    password_edit->setPlaceholderText("输入QQ密码");
    password_edit->setAlignment(Qt::AlignHCenter);
    password_edit->setEchoMode(QLineEdit::Password);
    password_edit->setStyleSheet(LINE_EDIT_STYLE);
    password_edit->setFixedHeight(EDIT_HEIGHT);
    password_edit->setValidator(new QRegularExpressionValidator(
        QRegularExpression("[a-zA-Z0-9]{6,32}"), password_edit));  // 设置输入框只能输入6-16位的字母或数字
    /* 获取验证码按钮和验证码 */
    code_edit = new QLineEdit();
    code_edit->setPlaceholderText("输入验证码");
    code_edit->setAlignment(Qt::AlignHCenter);
    code_edit->setStyleSheet(LINE_EDIT_STYLE);
    code_edit->setFixedSize(QSize(CODE_EDIT_WIDTH, EDIT_HEIGHT));
    // QLabel* code_image = new QLabel("验证码图片"); // just for test now
    verify_code = new VerifyCodeWidget(this);
    verify_code->setFixedHeight(EDIT_HEIGHT);
    verify_code->setStyleSheet(
        "QLabel{"
        "background-color: transparent;"
        "}");
    verify_code->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    /* 登录按钮 */
    login_button = new QPushButton("登录");
    BTN_STYLE.replace("QPushButton {", "QPushButton { border-radius: 5px; ");
    login_button->setStyleSheet(BTN_STYLE);
    login_button->setFixedHeight(BTN_HEIGHT);
    /* 切换手机号登录和注册按钮 */
    const QString TMP_BTN_STYLE =
        "QPushButton{"
        "font-size: 12px;"
        "color: #2D77E5;"
        "border: none;"
        "}";
    /* 创建水平布局容纳两个按钮 */
    QHBoxLayout* bottomLayout = new QHBoxLayout();
    bottomLayout->setSpacing(15);
    change_to_phone_num = new QPushButton("手机号登录");
    change_to_phone_num->setStyleSheet(TMP_BTN_STYLE);
    register_btn = new QPushButton("注册账号");
    register_btn->setStyleSheet(TMP_BTN_STYLE);
    /* 将按钮添加到水平布局，并设置拉伸因子 */
    bottomLayout->addWidget(change_to_phone_num, 1, Qt::AlignRight);  // 1:1比例
    bottomLayout->addWidget(register_btn, 1, Qt::AlignLeft);          // 1:1比例
    change_to_phone_num->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    register_btn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    /* 添加布局 */
    g_layout->addWidget(avatar, 0, 0, 2, 2, Qt::AlignHCenter | Qt::AlignTop);
    g_layout->addWidget(user_edit, 2, 0, 1, 2);
    g_layout->addWidget(password_edit, 3, 0, 1, 2);
    g_layout->addWidget(code_edit, 4, 0, 1, 1);
    g_layout->addWidget(verify_code, 4, 1, 1, 1);
    g_layout->addWidget(login_button, 5, 0, 1, 2);
    g_layout->addLayout(bottomLayout, 6, 0, 1, 2);
}

/// @brief 连接信号槽
void LoginWidget::connect_signals()
{
    /* 点击切换注册模式 - 只在父类连接 */
    connect(register_btn, &QPushButton::clicked, this, &LoginWidget::toggle_mode);
    /* 点击切换为手机号登录页面 */
    connect(change_to_phone_num, &QPushButton::clicked, this, &LoginWidget::switch_to_phone_login);
    /* 点击登录按钮 */
    connect(login_button, &QPushButton::clicked, this, &LoginWidget::handle_login_btn_clicked);
    /* 让敲击回车和点击登录or注册有同样的效果 */
    enter_shortcut  = new QShortcut(QKeySequence(Qt::Key_Return), this);  // 小键盘的回车键
    return_shortcut = new QShortcut(QKeySequence(Qt::Key_Enter), this);   // 主键盘的回车键
    connect(enter_shortcut, &QShortcut::activated, this, &LoginWidget::handle_login_btn_clicked);
    connect(return_shortcut, &QShortcut::activated, this, &LoginWidget::handle_login_btn_clicked);
}

void LoginWidget::switch_to_phone_login()
{
    PhoneLoginWidget* phone_login_widget = LoginWidget::get_phone_instance();
    phone_login_widget->move(this->pos());  // 保持窗口位置不变
    phone_login_widget->show();
    this->close();                          // 关闭当前窗口（会触发销毁）
}

/// @brief 点击登录或注册按钮
void LoginWidget::handle_login_btn_clicked()
{
    /* 参数检查 */
    const QString user_name        = user_edit->text();
    const QString password         = password_edit->text();
    const QString verify_code_text = code_edit->text();
    if (user_name.trimmed().isEmpty() || password.trimmed().isEmpty()) {
        Toast::showMessage("账号或密码为空!");
        return;
    }
    if (verify_code_text.trimmed().isEmpty()) {
        Toast::showMessage("请输入验证码!");
        return;
    }
    if (!verify_code->check_verify_code(verify_code_text)) {
        Toast::showMessage("验证码错误!");
        return;
    }
    /* 发请求 */
    connect(data_center, &DataCenter::user_login_done, this, &LoginWidget::handle_user_login_done, Qt::UniqueConnection);
    connect(data_center, &DataCenter::user_register_done, this, &LoginWidget::handle_user_register_done, Qt::UniqueConnection);
    if (login_mode) {
        /* 登录 */
        data_center->user_login_async(user_name, password);
    } else {
        /* 注册 */
        data_center->user_register_async(user_name, password);
    }
}

/// @brief 使用用户名密码登录结束, 可能是成功也可能失败
void LoginWidget::handle_user_login_done(bool is_ok, const QString& reason)
{
    if (!is_ok) {
        Toast::showMessage(reason);
        return;
    }
    /* 转到主界面 */
    MainWidget* main_widget = MainWidget::get_instance();
    main_widget->show();
    this->close();
}

/// @brief 使用用户名密码注册结束, 可能是成功也可能失败
void LoginWidget::handle_user_register_done(bool is_ok, const QString& reason)
{
    if (!is_ok) {
        Toast::showMessage(reason);
        return;
    }
    /* 转到登录界面 */
    code_edit->clear();
    verify_code->refresh_verify_code();
    this->toggle_mode();
}

//////////////////////////////////////////
/// @brief 使用手机号的登录界面
//////////////////////////////////////////
PhoneLoginWidget::PhoneLoginWidget(QWidget* parent)
    : LoginWidget(parent)
{
    /* 设置QWidget基本属性 */
    this->setStyleSheet(
        "QWidget{"
        "background-color: #FFFFFF;"
        "}");
    this->setParent(parent);
    this->setFixedSize(QSize(320, 320));
    this->setWindowTitle("手机号登录");
    this->setWindowIcon(QIcon(":/image/logo.png"));
    this->setAttribute(Qt::WA_DeleteOnClose);
    phone_init_ui();  // 初始化手机号登录界面
    connect_signals();
}

PhoneLoginWidget::~PhoneLoginWidget()
{
    LoginWidget::phone_instance = nullptr;  // 重置静态指针
}

/// @brief 手机号登录界面初始化UI
void PhoneLoginWidget::phone_init_ui()
{
    /* 初始化属性 */
    login_mode = true;  // 手机号登录模式
    user_edit->setPlaceholderText("输入手机号");
    change_to_phone_num->setText("QQ号登录");
    /* 不需要密码 */
    password_edit->hide();
    /* 将获取验证码图片换成按钮 */
    verify_code->hide();
    g_layout->removeWidget(verify_code);
    BTN_STYLE.replace("QPushButton {", "QPushButton { border-radius: 5px; ");
    BTN_STYLE           += "QPushButton:!enabled{ color:#000000; }";  // 禁用按钮的样式
    get_verify_code_btn  = new QPushButton("获取验证码");
    get_verify_code_btn->setStyleSheet(BTN_STYLE);
    get_verify_code_btn->setFixedSize(100, 35);
    g_layout->addWidget(get_verify_code_btn, 4, 1, 1, 1);
}

/// @brief 处理手机号登录的信号槽
void PhoneLoginWidget::connect_signals()
{
    /* 点击切换为QQ号登录页面 - 覆盖父类的连接 */
    disconnect(change_to_phone_num, &QPushButton::clicked, this, 0);  // 断开父类连接
    disconnect(login_button, &QPushButton::clicked, this, 0);
    disconnect(enter_shortcut, &QShortcut::activated, this, 0);
    disconnect(return_shortcut, &QShortcut::activated, this, 0);
    connect(get_verify_code_btn, &QPushButton::clicked, this, &PhoneLoginWidget::handle_get_verify_code_btn_clicked);
    connect(login_button, &QPushButton::clicked, this, &PhoneLoginWidget::handle_login_btn_clicked);
    connect(change_to_phone_num, &QPushButton::clicked, this, &PhoneLoginWidget::switch_to_qq_login);
    /* 让敲击回车和点击登录or注册有同样的效果 */
    connect(enter_shortcut, &QShortcut::activated, this, &PhoneLoginWidget::handle_login_btn_clicked);
    connect(return_shortcut, &QShortcut::activated, this, &PhoneLoginWidget::handle_login_btn_clicked);
}

/// @brief 点击了获取验证码按钮
void PhoneLoginWidget::handle_get_verify_code_btn_clicked()
{
    time_cnt = 60;  // 重置倒计时
    /* 参数检查 */
    const QString phone_num = user_edit->text();
    if (phone_num.trimmed().isEmpty()) {
        Toast::showMessage("手机号为空!");
        return;
    }
    QRegularExpression phoneRegex("^1[3-9]\\d{9}$");
    if (!phoneRegex.match(phone_num).hasMatch()) {
        Toast::showMessage("手机号格式不正确!!");
        return;
    }
    /* 每过60s只能发送1次验证码 */
    QTimer* timer = new QTimer(this);
    connect(timer, &QTimer::timeout, [=]() {
        LOG() << "计时器文字: " << QString::number(time_cnt) + "s";
        get_verify_code_btn->setText(QString::number(time_cnt) + "s");
        get_verify_code_btn->setEnabled(false);
        time_cnt--;
        if (time_cnt <= 0) {
            get_verify_code_btn->setText("获取验证码");
            get_verify_code_btn->setEnabled(true);
            time_cnt = 60;
            timer->stop();
            timer->deleteLater();
        }
    });
    timer->start(1000);
    this->phone_num = phone_num;
    connect(data_center, &DataCenter::get_phone_verify_code_done, [=]() {
        Toast::showMessage("验证码已发送");
    });
    get_verify_code_btn->setEnabled(false);
    /* 发送请求 */
    data_center->get_phone_verify_code_async(this->phone_num);
}

/// @brief 点击登录按钮
void PhoneLoginWidget::handle_login_btn_clicked()
{
    /* 参数检查 */
    const QString phone_num        = user_edit->text();
    const QString verify_code_text = code_edit->text();
    if (phone_num.trimmed().isEmpty()) {
        Toast::showMessage("手机号为空!");
        return;
    }
    if (phone_num != this->phone_num) {
        Toast::showMessage("手机号不一致!");
        return;
    }
    if (verify_code_text.trimmed().isEmpty()) {
        Toast::showMessage("请输入验证码!");
        return;
    }
    /* 发送请求 */
    connect(data_center, &DataCenter::phone_login_done, this, &PhoneLoginWidget::handle_phone_login_done);
    connect(data_center, &DataCenter::phone_register_done, this, &PhoneLoginWidget::handle_phone_register_done);
    if (login_mode) {
        /* 登录 */
        data_center->phone_login_async(phone_num, verify_code_text);
    } else {
        /* 注册 */
        data_center->phone_register_async(phone_num, verify_code_text);
    }
}

void PhoneLoginWidget::handle_phone_login_done(bool is_ok, const QString& reason)
{
    if (!is_ok) {
        Toast::showMessage(reason);
        return;
    }
    /* 转到主界面 */
    MainWidget* main_widget = MainWidget::get_instance();
    main_widget->show();
    this->close();
}

void PhoneLoginWidget::handle_phone_register_done(bool is_ok, const QString& reason)
{
    if (!is_ok) {
        Toast::showMessage(reason);
        return;
    }
    /* 转到登录界面 */
    code_edit->clear();
    toggle_mode();
}

/// @brief 切换到QQ登录
void PhoneLoginWidget::switch_to_qq_login()
{
    LoginWidget* login_widget = LoginWidget::get_instance();
    login_widget->move(this->pos());  // 保持窗口位置不变
    login_widget->show();
    this->close();                    // 关闭当前窗口（会触发销毁）
}

/// @brief 手机登录窗口的模式切换
void PhoneLoginWidget::toggle_mode()
{
    LoginWidget::toggle_mode();  // 调用父类实现
    this->setWindowTitle(login_mode ? "手机号登录" : "手机号注册");
    user_edit->setPlaceholderText("输入手机号");
    /* 把获取验证码时间归0 */
    time_cnt = 0;
}